# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: leon

from coin.exchange.base.kr_rest.currency import NativeCurrency
from coin.exchange.base.kr_rest.currency_constants import (
    BCHABC_BCHSV_FORK_TIME,
    BCHA_BCHN_FORK_TIME)
from coin.exchange.okex.kr_rest.constants import currency_list


def validate_native_currency(currency):
  assert type(currency) == str, str(currency)
  assert currency.lower() == currency
  assert currency.upper() in currency_list, currency


def to_native_currency(currency_str):
  if currency_str == 'BCHSV':
    native_currency_str = 'bsv'
  elif currency_str in ('BCHABC', 'BCHN'):
    native_currency_str = 'bch'
  else:
    native_currency_str = currency_str.lower()
  validate_native_currency(native_currency_str)
  return native_currency_str


def from_native_currency(native_currency_str, current_datetime):
  validate_native_currency(native_currency_str)
  if native_currency_str == 'bsv':
    assert current_datetime >= BCHABC_BCHSV_FORK_TIME, current_datetime
    currency_str = 'BCHSV'
  elif native_currency_str == 'bch':
    if current_datetime < BCHABC_BCHSV_FORK_TIME:
      currency_str = 'BCH'
    elif BCHABC_BCHSV_FORK_TIME <= current_datetime < BCHA_BCHN_FORK_TIME:
      currency_str = 'BCHABC'
    else:
      currency_str = 'BCHN'
  elif native_currency_str == 'bcha':
    assert BCHA_BCHN_FORK_TIME <= current_datetime
    currency_str = 'BCHA'
  else:
    currency_str = native_currency_str.upper()
  return currency_str


def convert_native_currency_v1_to_v3(native_currency_v1):
  assert native_currency_v1.lower() == native_currency_v1, native_currency_v1
  native_currency_v3 = native_currency_v1.upper()
  assert native_currency_v3 in currency_list, native_currency_v3
  return native_currency_v3


def convert_native_currency_v3_to_v1(native_currency_v3):
  # Okex V3 native currency symbol is the same as presto currency symbol.
  assert native_currency_v3 in currency_list, native_currency_v3
  native_currency_v1 = native_currency_v3.lower()
  return native_currency_v1


class OkexCurrency(NativeCurrency):
  _exchange = "Okex"

  def __init__(self, currency, native_currency):
    assert currency.upper() == currency, (currency, native_currency)
    assert native_currency.lower() == native_currency, (currency, native_currency)
    assert to_native_currency(currency) == native_currency, (currency, native_currency)
    # FIXME: For now, allow normalize to native not to be 1:1. Once current_date
    # arg is added, change this back.
    # assert currency_to_native(currency) == native_currency, (currency, native_currency)
    assert native_currency.upper() in currency_list, currency

    super().__init__(currency, native_currency)
    self._native_currency_v1 = self._native_currency
    self._native_currency_v3 = convert_native_currency_v1_to_v3(self._native_currency)

    # For futures, native currency is in upper case format.
    self._native_currency_futures = self.native_currency.upper()

  @property
  def native_currency_futures(self):
    return self._native_currency_futures

  @property
  def native_symbol_v1(self):
    return self._native_currency_v1

  @property
  def native_currency_v1(self):
    return self.native_symbol_v1

  @property
  def native_symbol_v3(self):
    return self._native_currency_v3

  @property
  def native_currency_v3(self):
    return self._native_currency_v3

  @classmethod
  def FromStrCurrencyImpl(cls, currency_str, current_datetime):
    return cls(currency_str, to_native_currency(currency_str))

  @classmethod
  def FromStrNativeCurrencyImpl(cls, native_currency_str, current_datetime):
    native_currency_str = native_currency_str.lower()
    currency_str = from_native_currency(native_currency_str, current_datetime)
    return cls(currency_str, native_currency_str)
